using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace tafei_thingsapi.Services
{
    public class HuaweiVideoService
    {
        private readonly HttpClient _httpClient;
        private readonly IConfiguration _configuration;
        private readonly ILogger<HuaweiVideoService> _logger;
        private readonly string _baseUrl;
        private readonly string _userId;
        private string _accessToken;

        public HuaweiVideoService(
            HttpClient httpClient,
            IConfiguration configuration,
            ILogger<HuaweiVideoService> logger)
        {
            _httpClient = httpClient;
            _configuration = configuration;
            _logger = logger;
            _baseUrl = _configuration["HuaweiVideo:BaseUrl"] ?? "https://ivm.cn-north-4.myhuaweicloud.com";
            _userId = _configuration["HuaweiVideo:UserId"] ?? throw new ArgumentNullException("HuaweiVideo:UserId is not configured");
        }

        public async Task<string> GetLiveUrlAsync(string deviceNumber)
        {
            try
            {
                await EnsureAccessTokenAsync();

                var request = new
                {
                    channels = new[]
                    {
                        new
                        {
                            device_id = FormatDeviceId(deviceNumber),
                            channel_id = $"15882478001310000001",
                            live_protocol = "HTTP_HLS",
                            stream_type = "PRIMARY_STREAM"
                        }
                    },
                    expire_time = 3600,
                    use_times = 1
                };

                var response = await _httpClient.PostAsync(
                    $"{_baseUrl}/v2/{_userId}/devices/channels/media/live-connections",
                    new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"));
                var responseContent = await response.Content.ReadAsStringAsync();
                _logger.LogInformation("获取live url: {ResponseContent}", responseContent);
                response.EnsureSuccessStatusCode();
                var liveResponse = JsonSerializer.Deserialize<LiveResponse>(responseContent);

                if (liveResponse?.live_connections?.Length > 0)
                {
                    var connection = liveResponse.live_connections[0];
                    if (connection.result.code == "IVM.0")
                    {
                        return connection.cloud_trans_connections?.live_url ?? 
                               connection.p2p_connections?.p2p_nodes?[0]?.address?[0];
                    }
                    else
                    {
                        _logger.LogError($"Failed to get live url: {connection.result.msg}");
                        throw new Exception($"Failed to get live url: {connection.result.msg}");
                    }
                }

                throw new Exception("No live connection found in response");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting live url");
                return null;
            }
        }

        private string FormatDeviceId(string deviceId)
        {
            return string.Format("99{0}132{1}", deviceId.Substring(8, 8), deviceId.Substring(16));
        }

        public async Task<BatchAddGBDevicesResponse> BatchAddGBDevicesAsync(BatchAddGBDevicesRequest request)
        {
            try
            {
                foreach (var device in request.devices)
                {
                    device.device_id = FormatDeviceId(device.device_id);
                }

                await EnsureAccessTokenAsync();

                var response = await _httpClient.PostAsync(
                    $"{_baseUrl}/v1/{_userId}/devices/gb/batch-add",
                    new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"));

                var responseContent = await response.Content.ReadAsStringAsync();
                _logger.LogInformation("批量添加GB设备: {ResponseContent}", responseContent);
                response.EnsureSuccessStatusCode();

                return JsonSerializer.Deserialize<BatchAddGBDevicesResponse>(responseContent);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "批量添加GB设备失败");
                throw;
            }
        }

        private async Task EnsureAccessTokenAsync()
        {
            if (string.IsNullOrEmpty(_accessToken))
            {
                var token = await GetAccessTokenAsync();
                _accessToken = token;
            }

            _httpClient.DefaultRequestHeaders.Remove("Access-Token");
            _httpClient.DefaultRequestHeaders.Add("Access-Token", _accessToken);
        }


        /*
        POST /v2/1090xxx/enterprises/access-token

        {
            "ak":"***",
            "sk":"***",
            "force_update":true
        }
        */
        private async Task<string> GetAccessTokenAsync()
        {
            try
            {
                var request = new
                {
                    ak = _configuration["HuaweiVideo:ak"],
                    sk = _configuration["HuaweiVideo:sk"],
                    force_update = true
                };
                var response = await _httpClient.PostAsync(
                    $"{_baseUrl}/v2/{_userId}/enterprises/access-token",
                    new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json"));

                var responseContent = await response.Content.ReadAsStringAsync();
                _logger.LogInformation("获取access token: {ResponseContent}", responseContent);
                response.EnsureSuccessStatusCode();
                var tokenResponse = JsonSerializer.Deserialize<TokenResponse>(responseContent);

                return tokenResponse?.access_token ?? throw new Exception("Failed to get access token");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting access token");
                throw;
            }
        }
    }

    public class LiveResponse
    {
        public int fail_num { get; set; }
        public LiveConnection[] live_connections { get; set; }
    }

    public class LiveConnection
    {
        public string device_id { get; set; }
        public string channel_id { get; set; }
        public CloudTransConnections cloud_trans_connections { get; set; }
        public P2PConnections p2p_connections { get; set; }
        public Result result { get; set; }
    }

    public class CloudTransConnections
    {
        public string live_url { get; set; }
    }

    public class P2PConnections
    {
        public string token { get; set; }
        public string device_state { get; set; }
        public P2PNode[] p2p_nodes { get; set; }
    }

    public class P2PNode
    {
        public string node_type { get; set; }
        public string address_type { get; set; }
        public string[] address { get; set; }
        public int tcp_port { get; set; }
        public int udp_port { get; set; }
    }

    public class Result
    {
        public string code { get; set; }
        public string msg { get; set; }
    }

    public class TokenResponse
    {
        public string access_token { get; set; }
        public string token_type { get; set; }
        public int expires_in { get; set; }
    }

    // 批量添加GB设备请求模型
    public class BatchAddGBDevicesRequest
    {
        public BatchAddGBDevicesReqItem[] devices { get; set; }
    }

    public class BatchAddGBDevicesReqItem
    {
        public string device_id { get; set; }
        public string device_name { get; set; }
        public string device_username { get; set; }
        public string device_password { get; set; }
        public string description { get; set; }
        public string algorithm { get; set; }
    }

    // 批量添加GB设备响应模型
    public class BatchAddGBDevicesResponse
    {
        public int failed_num { get; set; }
        public BatchAddGBDevicesRespItem[] devices { get; set; }
    }

    public class BatchAddGBDevicesRespItem
    {
        public string device_id { get; set; }
        public string sip_server_id { get; set; }
        public string sip_server_domain { get; set; }
        public string sip_server_host { get; set; }
        public string sip_server_port { get; set; }
        public Result result { get; set; }
    }
} 